﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WHMS.EntityClasses;
using WMS.HelperClasses;
using WHMS.HelperClasses;
using SD.LLBLGen.Pro.ORMSupportClasses;
using WHMS;

namespace WMS
{
    public partial class RemoveItemsForm : Form
    {
        WithdrawRequestEntity _currentRequest;
        WithdrawTransactionEntity _currentWithdrawTransaction;
        DataMngrFormBase<WithdrawRequestItemEntity> _tranItemsForm;
        List<ErrorProvider> _errorProviders;

        public RemoveItemsForm()
        {
            InitializeComponent();

            //EntityCollection<TransactionItemEntity> DepositTransactionItems = new EntityCollection<TransactionItemEntity>();
            //PrefetchPath2 prefetch = new PrefetchPath2(WHMS.EntityType.TransactionItemEntity);
            //prefetch.Add(TransactionItemEntity.PrefetchPathTransaction);
            //RelationPredicateBucket filter = new RelationPredicateBucket();
            //filter.Relations.Add(TransactionItemEntity.Relations.TransactionEntityUsingTransactionId);
            //filter.PredicateExpression.Add(TransactionFields.Type == "Deposit");
            //filter.PredicateExpression.Add(TransactionItemFields.CurrentBalance > 0);
            //SortExpression sorter = new SortExpression(TransactionFields.Date | SortOperator.Ascending);



            //DALHelper.FetchCollection(DepositTransactionItems, filter, prefetch, sorter);

            HideOrViewWeightCol();

            _currentRequest = new WithdrawRequestEntity();
            _currentWithdrawTransaction = new WithdrawTransactionEntity();

            LoadData();

            _errorProviders = new List<ErrorProvider>();

            EnableDisableControls();
        }

        private void HideOrViewWeightCol()
        {
            var weightCol = _transItemsGrid.Columns["Weight"];

            if (weightCol != null)
            {
                if (UserInfo.Roles.Where(r => r.ViewWorkshop == true).Count() > 0)
                {
                    weightCol.Visible = true;
                }
                else
                {
                    weightCol.Visible = false;
                }
            }
        }

        void LoadData()
        {
            DALHelper.FetchCollection(_removeTypes, null, null, new SortExpression(WithdrawalTypeFields.Order | SortOperator.Ascending));

            //DALHelper.FetchCollection(_removeTypes, null, null);

            FormsHelper.LoadComboBox(ProjectsDDL, ProjectFields.Id, ProjectFields.Name, () => Business.GetRunningAndGeneralProjects());
            //FormsHelper.LoadComboBox(StoresDDL, StoreFields.Id, StoreFields.Name, () => Business.GetStoresForKeeper());
            FormsHelper.LoadComboBox(StoresDDL, StoreFields.Id, StoreFields.Name, () => 
                Business.GetStoresByProjectId((int)ProjectsDDL.SelectedValue));
            
            FormsHelper.LoadComboBox(AccountantsDDL, UserFields.Id, UserFields.Name, (x, y) => Business.GetAccountants(x, y));
            FormsHelper.LoadComboBox(ContractorsDDL, ContractorFields.Id, ContractorFields.Name, (x, y) => DALHelper.GetDynamicList(x, y, null));

            FormsHelper.CheckStoresAndProjects(StoresDDL.Items, ProjectsDDL.Items, new List<Control>() { _transItemsGrid, SaveBtn }, NoStoresLbl, NoProjectsLbl);
        }

        private void SaveBtn_Click(object sender, EventArgs e)
        {
            Save(false);
        }

        private void Save(bool IsFinalSave)
        {
            if (!ValidateForm())
                return;

            if (!_currentWithdrawTransaction.IsNew)
            {
                if ((bool)DALHelper.GetValue(WithdrawTransactionFields.IsPriced, WithdrawTransactionFields.Id, _currentWithdrawTransaction.Id))
                {
                    RetrieveTransaction();
                    return;
                }
            }

            var transItems = new EntityCollection<TransactionItemEntity>();
            var transItemsToDelete = new EntityCollection<TransactionItemEntity>();

            if (_currentWithdrawTransaction.IsNew)
            {
                _currentWithdrawTransaction.AccountantId = _currentRequest.AccountantId;
                _currentWithdrawTransaction.ContractorId = _currentRequest.ContractorId;
                _currentWithdrawTransaction.Wrnumber = _currentRequest.RequestNumber;
                _currentWithdrawTransaction.Type = _currentRequest.Type;
                _currentWithdrawTransaction.Recipient = RecipientTB.Text;

                var transaction = new TransactionEntity()
                {
                    ProjectId = _currentRequest.ProjectId,
                    StoreId = GetSelectedStoreId(),
                    PermitNumber = PermitNumberTB.Text,
                    CreatedBy = UserInfo.UserId,
                    Date = WithdrawlDateDTP.Value.Date,
                    Type = "Withdraw"
                };

                _currentWithdrawTransaction.Transaction = transaction;
            }
            else
            {
                DALHelper.FetchCollection(transItems, new RelationPredicateBucket(TransactionItemFields.TransactionId == _currentWithdrawTransaction.TransactionId));
            }

            
            

            foreach (WithdrawRequestItemEntity item in _requestItems)
            {
                if (item.QuantityToBeWithdrawn > 0 && item.NewShelfId > 0)
                {
                    var q = (from t in transItems
                             where t.RequestItemId == item.Id
                             select t).FirstOrDefault();

                    TransactionItemEntity transItem;

                    if (q == null)
                    {
                        transItem = new TransactionItemEntity();
                    }
                    else
                    {
                        transItem = q;
                    }

                    //Get the Shelves in the Initial Balance to update their current balance
                    EntityCollection<InitialBalanceEntity> InitialBalance = new EntityCollection<InitialBalanceEntity>();

                    PrefetchPath2 prefetchinitial = new PrefetchPath2(WHMS.EntityType.InitialBalanceEntity);
                    prefetchinitial.Add(InitialBalanceEntity.PrefetchPathItem);

                    RelationPredicateBucket filterinitial = new RelationPredicateBucket();
                    filterinitial.Relations.Add(InitialBalanceEntity.Relations.ItemEntityUsingItemId);
                    filterinitial.PredicateExpression.AddWithAnd(InitialBalanceFields.ItemId == item.ItemId);
                    filterinitial.PredicateExpression.AddWithAnd(ItemFields.TypeId == 1);
                    filterinitial.PredicateExpression.AddWithAnd(InitialBalanceFields.StoreId == GetSelectedStoreId());
                    filterinitial.PredicateExpression.AddWithAnd(InitialBalanceFields.Balance > 0);
                    DALHelper.FetchCollection(InitialBalance, filterinitial, prefetchinitial);


                    //Get Transaction items to withdraw from their current balance and use their prices
                    EntityCollection<TransactionItemEntity> DepositTransactionItems = new EntityCollection<TransactionItemEntity>();
                    PrefetchPath2 prefetch = new PrefetchPath2(WHMS.EntityType.TransactionItemEntity);
                    prefetch.Add(TransactionItemEntity.PrefetchPathTransaction);
                    prefetch.Add(TransactionItemEntity.PrefetchPathItem);
                    RelationPredicateBucket filter = new RelationPredicateBucket();
                    filter.Relations.Add(TransactionItemEntity.Relations.TransactionEntityUsingTransactionId);
                    filter.Relations.Add(TransactionItemEntity.Relations.ItemEntityUsingItemId);
                    filter.PredicateExpression.AddWithAnd(TransactionFields.Type == "Deposit");
                    filter.PredicateExpression.AddWithAnd(ItemFields.TypeId == 1);
                    filter.PredicateExpression.AddWithAnd(TransactionItemFields.CurrentBalance > 0);
                    filter.PredicateExpression.AddWithAnd(TransactionItemFields.ItemId == item.ItemId);
                    filter.PredicateExpression.AddWithAnd(TransactionItemFields.StoreId == GetSelectedStoreId());
                    SortExpression sorter = new SortExpression(TransactionFields.Date | SortOperator.Ascending);
                    DALHelper.FetchCollection(DepositTransactionItems, filter, prefetch,sorter);

                   



                    //var price = Business.GetItemPrice(_currentRequest.ProjectId, transItem.StoreId, item.NewShelfId, item.ItemId);
                    //Variables initialized to be used to calcuate the price of selling
                    decimal ItemsCurrentBalanceTotal=0;
                    decimal ItemsPriceTotal = 0;
                    decimal ItemsQuantityTotal=0;
                    decimal price=0;


                    //This condition is true if the initial balance covers the quantity to be withdrawn
                    if (InitialBalance.Count > 0 && InitialBalance[0].CurrentBalance >= item.QuantityToBeWithdrawn)
                    {
                        ItemsPriceTotal += (decimal)InitialBalance[0].UnitPrice * (decimal)item.QuantityToBeWithdrawn;
                        ItemsQuantityTotal += item.QuantityToBeWithdrawn;
                           

                        if (IsFinalSave)
                        {

                            EntityCollection<StoreShelfBalanceEntity> StoreShelfBalances = new EntityCollection<StoreShelfBalanceEntity>();
                            RelationPredicateBucket filterStoreShelfBalance = new RelationPredicateBucket(StoreShelfBalanceFields.ShelfId == InitialBalance[0].ShelfId);
                            filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.StoreId == InitialBalance[0].StoreId);
                            filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.ProjectId == GetSelectedProjectId());
                            filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.ItemId == item.ItemId);
                            DALHelper.FetchCollection(StoreShelfBalances, filterStoreShelfBalance);

                            if (StoreShelfBalances.Count > 0)
                            {
                                StoreShelfBalances[0].Balance -= item.QuantityToBeWithdrawn;
                                DALHelper.SaveCollection(StoreShelfBalances);
                            }

                            InitialBalance[0].CurrentBalance -= item.QuantityToBeWithdrawn;
                            DALHelper.SaveCollection(InitialBalance);

                            item.WithdawedQuantity += item.QuantityToBeWithdrawn;

                            
                        }

                    } //If initial balance is not enough then take from initial balance plus from the oldest deposit transaction items
                    else
                    {
                        if (InitialBalance.Count > 0)
                        {
                            if (InitialBalance[0].CurrentBalance > 0)//First take from initial balance
                            {
                                ItemsCurrentBalanceTotal += (decimal)InitialBalance[0].CurrentBalance;
                                ItemsPriceTotal += (decimal)InitialBalance[0].UnitPrice * (decimal)InitialBalance[0].CurrentBalance;
                                ItemsQuantityTotal += (decimal)InitialBalance[0].CurrentBalance;
                              

                                if (IsFinalSave)//Affect the store shelf balance and initial balance only on final save
                                {

                                    EntityCollection<StoreShelfBalanceEntity> StoreShelfBalances = new EntityCollection<StoreShelfBalanceEntity>();
                                    RelationPredicateBucket filterStoreShelfBalance = new RelationPredicateBucket(StoreShelfBalanceFields.ShelfId == InitialBalance[0].ShelfId);
                                    filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.StoreId == InitialBalance[0].StoreId);
                                    filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.ProjectId == GetSelectedProjectId());
                                    filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.ItemId == item.ItemId);
                                    DALHelper.FetchCollection(StoreShelfBalances, filterStoreShelfBalance);

                                    if (StoreShelfBalances.Count > 0)
                                    {
                                        StoreShelfBalances[0].Balance -= (decimal)InitialBalance[0].CurrentBalance;
                                        DALHelper.SaveCollection(StoreShelfBalances);
                                    }

                                    InitialBalance[0].CurrentBalance = 0;
                                    DALHelper.SaveCollection(InitialBalance);

                                    item.WithdawedQuantity += (decimal)InitialBalance[0].CurrentBalance;
                                }
                             


                            }
                        }

                        for (int i = 0; i < DepositTransactionItems.Count; i++)//Take from the oldest deposit transaction items
                        {

                            ItemsCurrentBalanceTotal += (decimal)DepositTransactionItems[i].CurrentBalance;

                            if (ItemsCurrentBalanceTotal >= item.QuantityToBeWithdrawn)
                            {
                                for (int j = 0; j <= i; j++)
                                {
                                    EntityCollection<StoreShelfBalanceEntity> StoreShelfBalances = new EntityCollection<StoreShelfBalanceEntity>();
                                    RelationPredicateBucket filterStoreShelfBalance = new RelationPredicateBucket(StoreShelfBalanceFields.ShelfId == DepositTransactionItems[j].ShelfId);
                                    filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.StoreId == DepositTransactionItems[j].StoreId);
                                    filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.ProjectId == GetSelectedProjectId());
                                    filterStoreShelfBalance.PredicateExpression.AddWithAnd(StoreShelfBalanceFields.ItemId == item.ItemId);
                                    DALHelper.FetchCollection(StoreShelfBalances, filterStoreShelfBalance);


                                    if (j != i)
                                    {
                                        ItemsPriceTotal += DepositTransactionItems[j].UnitPrice * (decimal)DepositTransactionItems[j].CurrentBalance;
                                        ItemsQuantityTotal += (decimal)DepositTransactionItems[j].CurrentBalance;
                                        if (IsFinalSave)
                                        {
                                            if (StoreShelfBalances.Count > 0)
                                            {
                                                StoreShelfBalances[0].Balance -= (decimal)DepositTransactionItems[j].CurrentBalance;
                                                DALHelper.SaveCollection(StoreShelfBalances);
                                            }

                                            DepositTransactionItems[j].CurrentBalance = 0;

                                            item.WithdawedQuantity += (decimal)DepositTransactionItems[j].CurrentBalance;
                                        }

                                    }
                                    else
                                    {
                                        decimal QuantityLeft = 0;
                                        QuantityLeft = item.QuantityToBeWithdrawn - ItemsQuantityTotal;
                                        ItemsPriceTotal += DepositTransactionItems[j].UnitPrice * QuantityLeft;
                                        ItemsQuantityTotal += QuantityLeft;
                                        if (IsFinalSave)
                                        {
                                            DepositTransactionItems[j].CurrentBalance -= QuantityLeft;
                                            if (StoreShelfBalances.Count > 0)
                                            {
                                                StoreShelfBalances[0].Balance -= QuantityLeft;
                                                DALHelper.SaveCollection(StoreShelfBalances);
                                            }

                                            item.WithdawedQuantity += QuantityLeft;

                                        }
                                    }


                                    


                                }
                                break;
                            }
                        }

                        if (IsFinalSave)
                        {
                            DALHelper.SaveCollection(DepositTransactionItems);

                        }
                    }


                    price = ItemsPriceTotal / ItemsQuantityTotal;
                    //Insert new Transaction Item for withdraw operation
                    transItem.ShelfId = item.NewShelfId;
                    transItem.StoreId = _currentWithdrawTransaction.Transaction.StoreId.Value;
                    transItem.ItemId = item.ItemId;
                    transItem.Quantity = item.QuantityToBeWithdrawn;
                    transItem.RequestItemId = item.Id;
                    transItem.UnitPrice = price;
                    transItem.SellingPrice = price;// Business.GetItemCost(transItem.StoreId, transItem.ShelfId.Value, transItem.ItemId);

                    _currentWithdrawTransaction.Transaction.TransactionItems.Add(transItem);

                    DALHelper.SaveCollection(_requestItems);//Save WithdrawalRequestItem update for Withdrawd quatity in case of final save
                }
                else
                {
                    var q = (from t in transItems
                             where t.RequestItemId == item.Id
                             select t).FirstOrDefault();

                    if (q != null)
                    {
                        transItemsToDelete.Add(q);
                    }
                }
            }

            DALHelper.DeleteCollection(transItemsToDelete);
            if (DALHelper.SaveEntity(_currentWithdrawTransaction, true))
            {
                _currentRequest.IsApproved = true;
                DALHelper.SaveEntity(_currentRequest);

                RetrieveTransaction();
                MessageBox.Show("تم الحفظ بنجاح.");
            }
        }

        private bool ValidateForm()
        {
            var isValid = true;

            var controls = new List<TextBox>();
            controls.Add(RecipientTB);
            controls.Add(WRNumberTB);
            controls.Add(PermitNumberTB);

            if (_errorProviders == null)
            {
                _errorProviders = new List<ErrorProvider>();
            }
            else
            {
                foreach (var errorProvider in _errorProviders)
                {
                    errorProvider.Clear();
                    errorProvider.Dispose();
                }
            }
            foreach (var tb in controls)
            {
                if (string.IsNullOrEmpty(tb.Text.Trim()))
                {
                    var errorProvider = new ErrorProvider(this);
                    _errorProviders.Add(errorProvider);

                    errorProvider.SetError(tb, "يجب إدخال قيمة");
                    errorProvider.RightToLeft = true;

                    isValid = false;
                    continue;
                }
            }

            if (!ValidatePermitNumber())
                isValid = false;

            //_tranItemsForm.ValidateCollection();
            if (!_tranItemsForm.IsDataValid())
                isValid = false;

            if (_requestItems.Count <= 0)
            {
                isValid = false;
                MessageBox.Show("يجب إضافة أصناف", "خطأ فى الحفظ", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return isValid;
        }

        private void StoresDDL_SelectedIndexChanged(object sender, EventArgs e)
        {
            //ResetTransactionItems();

            //if (StoresDDL.SelectedItem == null)
            //	return;

            LoadShelves(GetSelectedStoreId());
            //GetShelves(null);
        }

        private void _transItemsGrid_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
        {
        }

        private void LoadRequestItems(int requestId)
        {
            if (_tranItemsForm != null)
            {
                _tranItemsForm.Dispose();
                _tranItemsForm = null;
            }

            var prefetch = new PrefetchPath2(EntityType.WithdrawRequestItemEntity);
            prefetch.Add(WithdrawRequestItemEntity.PrefetchPathItem).SubPath.Add(ItemEntity.PrefetchPathUnit_);

            var filter = new RelationPredicateBucket(WithdrawRequestItemFields.WithdrawRequestId == requestId);

            if (_currentWithdrawTransaction != null && _currentWithdrawTransaction.Id!=0 
                && (_currentWithdrawTransaction.TransactionStatus > 0 || 
                (_currentWithdrawTransaction.IsPriced.HasValue && _currentWithdrawTransaction.IsPriced.Value)))
            {
                var transactionItems = new EntityCollection<TransactionItemEntity>();

                DALHelper.FetchCollection(transactionItems, new RelationPredicateBucket(TransactionItemFields.TransactionId == _currentWithdrawTransaction.TransactionId));

                filter.PredicateExpression.Add(new FieldCompareRangePredicate(
                                                   WithdrawRequestItemFields.ItemId, null,
                                                   transactionItems.Select(x => x.ItemId)));
            }

            var label = new Label();
            _tranItemsForm = new DataMngrFormBase<WithdrawRequestItemEntity>(_requestItems, _transItemsGrid, bindingSource1, new Button(), label, label, filter, prefetch);
            _tranItemsForm.SetNumericFields(new List<int> { QuantityColumn.Index });
            //_tranItemsForm.SetMandatoryFields(new List<int>() {ShelfColumn.Index, QuantityColumn.Index});
            _tranItemsForm.RaiseSelectedChangedEventForComboBoxColumns(new List<int> { ShelfColumn.Index });
            _tranItemsForm.ComboboxColumnSelectionChanged += new DataMngrFormBase<WithdrawRequestItemEntity>.RaiseComboboxColumnSelectionChanged(_tranItemsForm_ComboboxColumnSelectionChanged);
            _tranItemsForm.RowValidating += new DataMngrFormBase<WithdrawRequestItemEntity>.RaiseRowValidating(_tranItemsForm_RowValidating);
        }

        private void _tranItemsForm_RowValidating(int rowIndex, ref bool hasErrors)
        {
            var availableQuantityCell = _transItemsGrid.Rows[rowIndex].Cells[AvailableAmountColumn.Index];
            var availaleQuantity = (availableQuantityCell == null) ? 0 : availableQuantityCell.Value;

            var remainderQuantityCell = _transItemsGrid.Rows[rowIndex].Cells[RemainderQuantityColumn.Index];
            var remainderQuantity = (remainderQuantityCell == null) ? 0 : remainderQuantityCell.Value;

            var quantityCell = _transItemsGrid.Rows[rowIndex].Cells[QuantityColumn.Index];
            var quantity = quantityCell.Value;

            if (quantity == null)
                return;

            //if ((decimal)quantity <= 0)
            //{
            //    quantityCell.ErrorText = "الكمية المراد صرفها يجب أن تكون رقم موجب.";
            //    hasErrors = true;
            //    return;
            //}

            if ((availaleQuantity != null && (decimal)quantity <= (decimal)availaleQuantity) && (decimal)quantity <= (decimal)remainderQuantity)
            {
                quantityCell.ErrorText = string.Empty;
                return;
            }

            if ((decimal)quantity > (decimal)remainderQuantity)
            {
                quantityCell.ErrorText = "الكمية المراد صرفها يجب أن لا تتعدى الكمية المتبقية من الطلب.";
                hasErrors = true;
                return;
            }

            //quantityCell.ErrorText = "الكمية المراد صرفها يجب أن لا تتعدى الكمية المتاحة فى المخزن.";
            //hasErrors = true;
        }

        private void _tranItemsForm_ComboboxColumnSelectionChanged(object selectedValue)
        {
            if (selectedValue == null)
                return;

            if (selectedValue is int)
            {
                if (_transItemsGrid.CurrentCell.ColumnIndex == ShelfColumn.Index)
                {
                    var itemId = (int)_transItemsGrid.CurrentRow.Cells[ItemIdColumn.Index].Value;
                    var shelfId = (int)selectedValue;

                    //_transItemsGrid.CurrentRow.Cells[AvailableAmountColumn.Index].Value = Business.GetItemBalance(GetSelectedProjectId(), _currentWithdrawTransaction.Transaction.StoreId.Value, shelfId, itemId, _showStoppedProjectsItemsCB.Checked);
                    _transItemsGrid.CurrentRow.Cells[AvailableAmountColumn.Index].Value = Business.GetItemBalance(GetSelectedProjectId(), GetStoreId(), shelfId, itemId, _showStoppedProjectsItemsCB.Checked);
                    //_transItemsGrid.CurrentRow.Cells[4].Value = Business.GetItemPrice(GetSelectedStoreId(), shelfId, itemId);
                }
            }
        }

        #region shelves
        private void LoadShelves(int storeId)
        {
            foreach (DataGridViewRow row in _transItemsGrid.Rows)
            {
                var control = (_transItemsGrid[ShelfColumn.Index, row.Index] as DataGridViewComboBoxCell);
                LoadShelves(control, row.Index, storeId);
            }

            var index = 0;
            foreach (WithdrawRequestItemEntity item in _requestItems)
            {
                decimal availableQuantity = new decimal();
                string shelfCode = string.Empty;

                item.NewShelfId = Business.GetWithdrawShelfId(_currentRequest.ProjectId, storeId, item.ItemId, item.RemainderQuantity, _currentRequest.Type, out availableQuantity, out shelfCode);
                item.AvailableQantity = availableQuantity;
                item.NewShelfCode = shelfCode;

                //_transItemsGrid.CurrentRow.Cells[AvailableAmountColumn.Index].Value = Business.GetItemBalance(_currentRequest.ProjectId, storeId, item.NewShelfId, item.ItemId, _showStoppedProjectsItemsCB.Checked);
                //item.AvailableQantity = Business.GetItemBalance(_currentRequest.ProjectId, storeId, item.NewShelfId, item.ItemId, _showStoppedProjectsItemsCB.Checked);

                _transItemsGrid.Rows[index].Cells[NewShelfCode.Index].Value = item.NewShelfCode;
                _transItemsGrid.Rows[index].Cells[NewShelfCode.Index].Selected = true;
                _transItemsGrid.Rows[index].Cells[NewShelfCode.Index].Selected = false;

                _transItemsGrid.Rows[index].Cells[AvailableAmountColumn.Index].Value = item.AvailableQantity;
                _transItemsGrid.Rows[index].Cells[AvailableAmountColumn.Index].Selected = true;
                _transItemsGrid.Rows[index].Cells[AvailableAmountColumn.Index].Selected = false;
                index++;
            }

            if (_transItemsGrid.Rows.Count > 0)
                _transItemsGrid.Rows[0].Cells[QuantityColumn.Index].Selected = true;
        }
        private void LoadShelves(DataGridViewComboBoxCell control, int rowIndex, int storeId)
        {
            var itemIdValue = _transItemsGrid.Rows[rowIndex].Cells[ItemIdColumn.Index].Value;
            if (itemIdValue == null)
                return;

            control.DisplayMember = ShelfFields.Code.Name;
            control.ValueMember = ShelfFields.Id.Name;

            var shelves = GetShelves((int)itemIdValue, storeId);
            var bindingsource = new BindingSource();
            bindingsource.DataSource = shelves;
            control.DataSource = bindingsource;

            if (shelves.Count <= 0)
            {
                //MessageBox.Show("لا يوجد رصيد بالمخزن المختار", "تنبيه", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                _transItemsGrid.Rows[rowIndex].Cells[ShelfColumn.Index].ErrorText = "لا يوجد رصيد بالمخزن";
            }
            else
            {
                _transItemsGrid.Rows[rowIndex].Cells[ShelfColumn.Index].ErrorText = string.Empty;
            }
        }
        private EntityCollection<ShelfEntity> GetShelves(int itemId, int storeId)
        {
            var filter = GetShelvesFilter(itemId, storeId);


            var shelves = new EntityCollection<ShelfEntity>();
            DALHelper.FetchCollection(shelves, filter);
            return shelves;
        }
        private RelationPredicateBucket GetShelvesFilter(int itemId, int storeId)
        {
            var shelfFilter = new PredicateExpression(StoreShelfBalanceFields.ItemId == itemId);
            shelfFilter.Add(StoreShelfBalanceFields.StoreId == storeId);

            var projectFilter = new PredicateExpression(StoreShelfBalanceFields.ProjectId == GetSelectedProjectId());
            if (_showStoppedProjectsItemsCB.Checked)
            {
                projectFilter.AddWithOr(new FieldCompareSetPredicate(StoreShelfBalanceFields.ProjectId, null, ProjectFields.Id, null, SetOperator.In, new PredicateExpression(ProjectFields.Status == "جارى"), true));
                projectFilter.AddWithOr(new FieldCompareSetPredicate(StoreShelfBalanceFields.ProjectId, null, ProjectFields.Id, null, SetOperator.In, new PredicateExpression(ProjectFields.IsGeneral == true)));
            }
            shelfFilter.Add(projectFilter);

            var filter = new RelationPredicateBucket(new FieldCompareSetPredicate(ShelfFields.Id, null, StoreShelfBalanceFields.ShelfId, null, SetOperator.In, shelfFilter));
            filter.PredicateExpression.Add(ShelfFields.StoreId == storeId);
            return filter;
        }
        #endregion

        private int GetSelectedStoreId()
        {
            if (StoresDDL.SelectedItem == null)
                return 0;

            //return (int)((System.Data.DataRowView)(StoresDDL.SelectedItem)).Row.ItemArray[0];
            return int.Parse(((System.Data.DataRowView)(StoresDDL.SelectedItem)).Row.ItemArray[0].ToString());
        }
        private int GetStoreId()
        {
            if (_currentWithdrawTransaction.Transaction == null)
            {
                if (StoresDDL.SelectedItem == null)
                    return 0;

                //return (int)((System.Data.DataRowView)(StoresDDL.SelectedItem)).Row.ItemArray[0];
                return int.Parse(((System.Data.DataRowView)(StoresDDL.SelectedItem)).Row.ItemArray[0].ToString());
            }

            if (_currentWithdrawTransaction.Transaction.StoreId.HasValue)
                return _currentWithdrawTransaction.Transaction.StoreId.Value;

            return 0;
        }
        private int GetSelectedProjectId()
        {
            return (int)((System.Data.DataRowView)(ProjectsDDL.SelectedItem)).Row.ItemArray[0];
        }

        private bool ValidatePermitNumber()
        {
            return FormsHelper.ValidatePermitNumber(this, PermitNumberTB, _errorProviders, "Withdraw", _currentWithdrawTransaction.TransactionId);
        }

        private void PermitNumberTB_Leave(object sender, EventArgs e)
        {
            ValidatePermitNumber();
        }

        private void RetrieveRequestBtn_Click(object sender, EventArgs e)
        {
            RetrieveRequest();
        }

        private void RetrieveBtn_Click(object sender, EventArgs e)
        {
            RetrieveTransaction();
        }

        private void NewBtn_Click(object sender, EventArgs e)
        {
            ResetForm();
        }

        private void RetrieveTransaction()
        {
            if (string.IsNullOrEmpty(PermitNumberTB.Text.Trim()))
                return;

            var requestTypes = new string[3] { "G", "S", "M" };

            var collection = new EntityCollection<WithdrawTransactionEntity>();
            var filter = new RelationPredicateBucket(TransactionFields.PermitNumber == PermitNumberTB.Text.Trim());
            filter.Relations.Add(WithdrawTransactionEntity.Relations.TransactionEntityUsingTransactionId);

            filter.PredicateExpression.Add(
                new FieldCompareSetPredicate(WithdrawTransactionFields.Wrnumber, null, WithdrawRequestFields.RequestNumber, null, SetOperator.In, new PredicateExpression(WithdrawRequestFields.Type == requestTypes), false));

            var prefetch = new PrefetchPath2(EntityType.WithdrawTransactionEntity);
            prefetch.Add(WithdrawTransactionEntity.PrefetchPathTransaction);

            DALHelper.FetchCollection(collection, filter, prefetch);

            if (collection.Count <= 0)
            {
                //_currentWithdrawTransaction = new WithdrawTransactionEntity();
                ResetForm();
            }
            else
            {
                _currentWithdrawTransaction = collection[0];
                RetrieveRequest(_currentWithdrawTransaction.Wrnumber);

                _WithdrawBS.DataSource = _currentWithdrawTransaction;
                _TransBS.DataSource = _currentWithdrawTransaction.Transaction;

               var transItems = new EntityCollection<TransactionItemEntity>();

                DALHelper.FetchCollection(transItems, new RelationPredicateBucket(TransactionItemFields.TransactionId == _currentWithdrawTransaction.TransactionId));
                foreach (WithdrawRequestItemEntity requestItem in _requestItems)
                {
                    var q = (from t in transItems
                             where t.ItemId == requestItem.ItemId
                             select t).FirstOrDefault();

                    if (q == null)
                        continue;

                    requestItem.NewShelfId = q.ShelfId.Value;
                    requestItem.QuantityToBeWithdrawn = q.Quantity;
                    requestItem.AvailableQantity = Business.GetItemBalance(_currentWithdrawTransaction.Transaction.ProjectId, _currentWithdrawTransaction.Transaction.StoreId.Value, requestItem.NewShelfId, requestItem.ItemId, _showStoppedProjectsItemsCB.Checked);
                }
            }

            //_WithdrawBS.DataSource = _currentWithdrawTransaction;
            //_TransBS.DataSource = _currentWithdrawTransaction.Transaction;

            ValidatePermitNumber();

            EnableDisableControls();
        }

        private void RetrieveRequest()
        {
            var requestNumber = WRNumberTB.Text;
            ResetForm();
            RetrieveRequest(requestNumber);
            EnableDisableControls();
        }
        private void RetrieveRequest(string requestNumber)
        {
            if (string.IsNullOrEmpty(requestNumber.Trim()))
                return;

            var collection = new EntityCollection<WithdrawRequestEntity>();

            var filter = new RelationPredicateBucket(WithdrawRequestFields.RequestNumber == requestNumber.Trim());

            DALHelper.FetchCollection(collection, filter);

            if (collection.Count <= 0)
            {
                _currentRequest = new WithdrawRequestEntity();
                _WRequestBS.DataSource = _currentRequest;
            }
            else
            {
                _currentRequest = collection[0];
                _WRequestBS.DataSource = _currentRequest;
            }
            //_requestItems.Clear();
            //DALHelper.FetchCollection(_requestItems, new RelationPredicateBucket(WithdrawRequestItemFields.WithdrawRequestId == _currentRequest.Id));	

            LoadRequestItems(_currentRequest.Id);
            LoadShelves(GetStoreId());
            //EnableDisableControls();

            // Reload stores depending on project
            FormsHelper.LoadComboBox(StoresDDL, StoreFields.Id, StoreFields.Name, () =>
                Business.GetStoresByProjectId(ProjectsDDL.SelectedValue));
        }

        private void ResetForm()
        {
            _currentRequest = new WithdrawRequestEntity();
            _currentWithdrawTransaction = new WithdrawTransactionEntity();
            _currentWithdrawTransaction.Transaction = new TransactionEntity();
            _requestItems.Clear();

            _WithdrawBS.DataSource = _currentWithdrawTransaction;
            _TransBS.DataSource = _currentWithdrawTransaction.Transaction;
            _WRequestBS.DataSource = _currentRequest;

            EnableDisableControls();
        }

        void EnableDisableControls()
        {
            if (_currentWithdrawTransaction.TransactionStatus == 1)
            {
                _alreadyPricedLbl.Text = "* إذن الصرف تم حفظه نهائيا ويمكن تسعيره فقط  !";
            }
            else if (_currentWithdrawTransaction.TransactionStatus == 2)
            {
                _alreadyPricedLbl.Text = "* إذن الصرف تم تسعيره و لا يمكن تغيير بياناته !";
            }

            var isPriced = (_currentWithdrawTransaction.IsPriced.HasValue) ? _currentWithdrawTransaction.IsPriced.Value : false;
            var isSubmitted = _currentWithdrawTransaction.TransactionStatus > 0;

            var isEditable = !(isPriced || isSubmitted);

            _transItemsGrid.Enabled = isEditable;// !isPriced;
            SaveBtn.Enabled = isEditable;// !isPriced;
            SubmitBtn.Enabled = isEditable;
            bindingNavigator1.Enabled = isEditable;//!isPriced;
            _alreadyPricedLbl.Visible = !isEditable;
            StoresDDL.Enabled = isEditable;//!isPriced;
            RecipientTB.Enabled = isEditable;//!isPriced;
            WithdrawlDateDTP.Enabled = isEditable;//!isPriced;
            _showStoppedProjectsItemsCB.Enabled = isEditable;//!isPriced;

            NewBtn.Enabled = !_currentWithdrawTransaction.IsNew;
            DeleteBtn.Enabled = !_currentWithdrawTransaction.IsNew && isEditable;

            _showStoppedProjectsItemsCB.Checked = (_currentRequest.Type == "G");
            _showStoppedProjectsItemsCB.Enabled = (_currentRequest.Type != "G");
        }

        private void _transItemsGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            var itemIdValue = _transItemsGrid.Rows[e.RowIndex].Cells[ItemIdColumn.Index].Value;
            if (itemIdValue == null)
                return;

            // Part of replacing combo box of shelves with window of shleves to enable multiple choices
            if (e.ColumnIndex == ShelfColumnFromWindow.Index)
            {
                var filter = GetShelvesFilter((int)itemIdValue, GetSelectedStoreId());
                var searchForm = new FrmGeneralMultiSelecteItem("Shelf",filter);
                if (searchForm.ShowDialog() == DialogResult.OK)
                {
                    var text = string.Join(",", searchForm.SelectedItemCodes);
                    _transItemsGrid.Rows[e.RowIndex].Cells[ShelfColumnFromWindow.Index].Value = text;

                    decimal accumulatedBalance = 0;
                    foreach (var shelfId in searchForm.SelectedItemIds)
                    {
                        accumulatedBalance += Business.GetItemBalance(GetSelectedProjectId(), GetStoreId(), shelfId, (int)itemIdValue,
                            _showStoppedProjectsItemsCB.Checked);    
                    }
                    // amount for all choosed shelves
                    _transItemsGrid.CurrentRow.Cells[AvailableAmountColumn.Index].Value = accumulatedBalance;
                }
            }
            ///////////////

            if (e.ColumnIndex != QuantityColumn.Index)
                return;
            
            var form = new UnitConverterForm((int)itemIdValue);
            if (form.ShowDialog() == DialogResult.OK)
            {
                _transItemsGrid.SuspendLayout();
                _transItemsGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = form.Value;
                _transItemsGrid.UpdateCellValue(e.ColumnIndex, e.RowIndex);
                _transItemsGrid.ResumeLayout(true);
            }

        }

        private void SearchBtn_Click(object sender, EventArgs e)
        {
            var requestTypes = new string[3] { "G", "S", "M" };

            var filter = new RelationPredicateBucket(TransactionFields.Type == "Withdraw");
            filter.Relations.Add(TransactionEntity.Relations.ProjectEntityUsingProjectId);
            filter.Relations.Add(TransactionEntity.Relations.WithdrawTransactionEntityUsingTransactionId);
            //filter.PredicateExpression.Add(ProjectFields.IsGeneral == false);
            filter.PredicateExpression.Add(
                new FieldCompareSetPredicate(WithdrawTransactionFields.Wrnumber, null, WithdrawRequestFields.RequestNumber, null, SetOperator.In, new PredicateExpression(WithdrawRequestFields.Type == requestTypes), false));

            var searchForm = new SearchForm(TransactionFields.PermitNumber, TransactionFields.ProjectId, TransactionFields.Date, filter, null);
            if (searchForm.ShowDialog() == DialogResult.OK)
            {
                PermitNumberTB.Text = searchForm.SelectedNumber;
                RetrieveTransaction();
            }
        }

        private void SearchRequestBtn_Click(object sender, EventArgs e)
        {
            var filter = new RelationPredicateBucket();
            filter.Relations.Add(WithdrawRequestEntity.Relations.ProjectEntityUsingProjectId);
            //filter.PredicateExpression.Add(ProjectFields.IsGeneral == false);

            var searchForm = new SearchForm(WithdrawRequestFields.RequestNumber, WithdrawRequestFields.ProjectId, WithdrawRequestFields.RequestDate, filter, () => Business.GetRunningProjects());
            if (searchForm.ShowDialog() == DialogResult.OK)
            {
                WRNumberTB.Text = searchForm.SelectedNumber;
                RetrieveRequest();
            }
        }

        private void DeleteBtn_Click(object sender, EventArgs e)
        {
            var form = new DeleteConfirmationForm();

            if (form.ShowDialog() == DialogResult.Yes)
            {
                if (DALHelper.DeleteEntity(_currentWithdrawTransaction.Transaction))
                {
                    ResetForm();
                }
            }
        }

        private void SubmitBtn_Click(object sender, EventArgs e)
        {
            var form = new SaveConfirmationForm();

            if (form.ShowDialog() == DialogResult.Yes)
            {
                _currentWithdrawTransaction.TransactionStatus = 1;
                Save(true);
                //Business.RemoveItems(_currentWithdrawTransaction.TransactionId);
            }
        }
    }
}
